package com.label.Service.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.label.Dao.JobMapper;
import com.label.Dao.PersonsMapper;
import com.label.Dao.StrategyMapper;
import com.label.Model.Do.Job;
import com.label.Model.Do.Persons;
import com.label.Model.Do.Strategy;
import com.label.Model.Query.JobQuery;
import com.label.Service.JobService;
import com.label.Utils.UserUtil;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@Transactional(rollbackFor = {Exception.class})
public class JobServiceImpl extends ServiceImpl<JobMapper, Job> implements JobService {

    @Resource
    private JobMapper jobMapper;

    @Resource
    private StrategyMapper strategyMapper;

    @Resource
    private PersonsMapper personsMapper;

    @Override
    public List<Job> getAllJob(){
        List<Job> jobs=jobMapper.selectList(new QueryWrapper<>());
        List<Long> strategyIds=jobs.stream().filter(p->p.getStrategyId()!=null).map(p->Long.valueOf(p.getStrategyId())).collect(Collectors.toList());
        Map<String,Object> strategies=strategyIds.isEmpty()?new HashMap<>():strategyMapper.selectBatchIds(strategyIds).stream().collect(Collectors.toMap(p->p.getId().toString(), p->p));

        List<Long> personIds=jobs.stream().map(Job::getPersonsId).collect(Collectors.toList());
        Map<Long,Object> persons=personIds.isEmpty()?new HashMap<>():personsMapper.selectBatchIds(personIds).stream().collect(Collectors.toMap(Persons::getId, p->p));
        jobs.forEach(p->{if(p.getPersonsId()!=null && persons.containsKey(p.getPersonsId()))p.setPersons((Persons) persons.get(p.getPersonsId()));if(p.getStrategyId()!=null && strategies.containsKey(p.getStrategyId()))p.setStrategy((Strategy) strategies.get(p.getStrategyId()));});
        return jobs;
    }

    @Override
    public Job getOneById(JobQuery jobQuery){
        Job job=jobMapper.selectById(jobQuery.getId());
        if(job.getStrategyId()!=null)
            job.setStrategy(strategyMapper.getOneById(Long.valueOf(job.getStrategyId())));
        if(job.getPersonsId()!=null)
            job.setPersons(personsMapper.selectById(job.getPersonsId()));
        return job;
    }

    @Override
    public List<Job> getAllByName(JobQuery jobQuery){
        List<Job> jobs=jobMapper.selectList(new QueryWrapper<Job>().lambda().like(Job::getName,jobQuery.getName()));
        List<Long> strategyIds=jobs.stream().filter(p->p.getStrategyId()!=null).map(p->Long.valueOf(p.getStrategyId())).collect(Collectors.toList());
        Map<String,Object> strategies=strategyIds.isEmpty()?new HashMap<>():strategyMapper.selectBatchIds(strategyIds).stream().collect(Collectors.toMap(p->p.getId().toString(), p->p));

        List<Long> personIds=jobs.stream().map(Job::getPersonsId).collect(Collectors.toList());
        Map<Long,Object> persons=personIds.isEmpty()?new HashMap<>():personsMapper.selectBatchIds(personIds).stream().collect(Collectors.toMap(Persons::getId, p->p));
        jobs.forEach(p->{if(p.getPersonsId()!=null && persons.containsKey(p.getPersonsId()))p.setPersons((Persons) persons.get(p.getPersonsId()));if(p.getStrategyId()!=null && strategies.containsKey(p.getStrategyId()))p.setStrategy((Strategy) strategies.get(p.getStrategyId()));});
        return jobs;
    }

    @Override
    public List<Job> getAllByStates(JobQuery jobQuery){
        if(jobQuery.getStates()!=null&&!jobQuery.getStates().isEmpty()) {
            List<Job> jobs = jobMapper.selectList(new QueryWrapper<Job>().lambda().in(Job::getState, jobQuery.getStates()));
            List<Long> strategyIds = jobs.stream().filter(p -> p.getStrategyId() != null).map(p -> Long.valueOf(p.getStrategyId())).collect(Collectors.toList());
            Map<String, Object> strategies = strategyIds.isEmpty() ? new HashMap<>() : strategyMapper.selectBatchIds(strategyIds).stream().collect(Collectors.toMap(p -> p.getId().toString(), p -> p));

            List<Long> personIds = jobs.stream().map(Job::getPersonsId).collect(Collectors.toList());
            Map<Long, Object> persons = personIds.isEmpty() ? new HashMap<>() : personsMapper.selectBatchIds(personIds).stream().collect(Collectors.toMap(Persons::getId, p -> p));

            jobs.forEach(p -> {
                if (p.getPersonsId() != null && persons.containsKey(p.getPersonsId()))
                    p.setPersons((Persons) persons.get(p.getPersonsId()));
                if (p.getStrategyId() != null && strategies.containsKey(p.getStrategyId()))
                    p.setStrategy((Strategy) strategies.get(p.getStrategyId()));
            });
            return jobs;
        }
        return new ArrayList<>();
    }

    @Override
    public List<Job> getMyJobs(){
        List<Job> jobs=jobMapper.selectList(new QueryWrapper<Job>().lambda().eq(Job::getCreator,UserUtil.getUser().getUserName()));
        List<Long> strategyIds=jobs.stream().filter(p->p.getStrategyId()!=null).map(p->Long.valueOf(p.getStrategyId())).collect(Collectors.toList());
        Map<String,Object> strategies=strategyIds.isEmpty()?new HashMap<>():strategyMapper.selectBatchIds(strategyIds).stream().collect(Collectors.toMap(p->p.getId().toString(), p->p));

        List<Long> personIds=jobs.stream().map(Job::getPersonsId).collect(Collectors.toList());
        Map<Long,Object> persons=personIds.isEmpty()?new HashMap<>():personsMapper.selectBatchIds(personIds).stream().collect(Collectors.toMap(Persons::getId, p->p));

        jobs.forEach(p->{if(p.getPersonsId()!=null && persons.containsKey(p.getPersonsId()))p.setPersons((Persons) persons.get(p.getPersonsId()));if(p.getStrategyId()!=null && strategies.containsKey(p.getStrategyId()))p.setStrategy((Strategy) strategies.get(p.getStrategyId()));});
        return jobs;
    }

    @Override
    public Boolean addJob(JobQuery jobQuery){
        jobMapper.insert(BeanUtil.copyProperties(jobQuery,Job.class));
        return true;
    }

    @Override
    public Boolean delJob(JobQuery jobQuery){
        jobMapper.deleteById(jobQuery.getId());
        return true;
    }

    @Override
    public Boolean updateJob(JobQuery jobQuery){
        Job test=BeanUtil.copyProperties(jobQuery,Job.class);
        jobMapper.updateById(test);
        return true;
    }
}
